home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
422_02
/
dosutil
/
mterm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-20
|
17KB
|
679 lines
/*
* MICRO-Terminal:
*
* This is a very simple communications program, which provides
* a subset ANSI (VT100) terminal emulation, and basic XMODEM
* (with checksum) file transfer.
*
* If HOTKEYS are specified on the command line, MTERM will install
* itself as a TSR (Ram-Resident) program, which can be invoked at
* any time by pressing the HOTKEYS. Available HOTKEYS are:
* L - Left SHIFT
* R - Right SHIFT
* A - ALT
* C - CONTROL
* S - SysRq (Caution: some systems may not like this one)
*
* EG: mterm LR (Install with LEFT+RIGHT SHIFT for hotkeys)
*
* This demonstrates the use of the MICRO-C video interface
* and communications library functions for the IBM/PC, as well
* as the "SAVE_VIDEO", "RESTORE_VIDEO" and "TSR" functions.
*
* Copyright 1990-1994 Dave Dunfield
* All rights reserved.
*
* Permission granted for personal (non-commercial) use only.
*
* Compile command: cc mterm -fop
*/
#include <stdio.h> /* Standard I/O definitions */
#include <comm.h> /* Comm I/O definitions */
#include <video.h> /* Video I/O definitions */
#include <file.h> /* File I/O definitions */
#include <tsr.h> /* Tsr function definitions */
/* Screen output positions */
#define SETROW 3 /* Screen row for settings display */
#define MSGROW 20 /* Screen row for messages */
#define MENROW 7 /* Screen row for menu items */
#define MAICOL 0 /* Screen column for main menu */
#define SUBCOL 20 /* Screen column for sub menu */
#define FILCOL 5 /* Screen column for file prompt */
#define FILSIZ 50 /* Maximum size of file name */
/* XMODEM parameters */
#define BLOCK_SIZE 128 /* size of transmit blocks */
#define RETRYS 10 /* maximum number of retrys */
#define SOH_TIMEOUT 5 /* How long to wait for start of packet */
#define RX_TIMEOUT 2 /* How long in wait for chars in packet */
#define ACK_TIMEOUT 5 /* How long to wait for acknowlege */
/* Line control codes */
#define SOH 0x01 /* start of header */
#define ACK 0x06 /* Acknowledge */
#define NAK 0x15 /* Negative acknowledge */
#define CAN 0x18 /* Cancel */
#define EOT 0x04 /* end of text */
/* Menu text tables (Used by 'vmenu') */
char *main_menu[] = {
"Terminal Emulation",
"XMODEM Download",
"XMODEM Upload",
"Serial port config",
"Exit to DOS",
0 };
char *setup_menu[] = {
"Comm port",
"Baudrate",
"Data bits",
"Parity",
"Stop bits",
"Xon/Xoff",
0 };
/* Uart configuration data tables */
unsigned baudvalue[] =
{ _110, _300, _1200, _2400, _4800, _9600, _19200, _38400 };
char *baudtext[] =
{ "110", "300", "1200", "2400", "4800", "9600", "19200", "38400", 0 };
char *databits[] = { "Five", "Six", "Seven", "Eight", 0 };
char *parity[] = { "Odd", "Even", "Mark", "Space", "None", 0 };
char *onetwo[] = { "One", "Two", 0 };
char *onefour[] = { "One", "Two", "Three", "Four", 0 };
char *flowctrl[] = { "Disabled", "Enabled", 0 };
/* Communications configuration parameters */
int comm = 0, baud = 5, data = 3, par = 4, stop = 0, flow = 1;
/* Misc global variables */
setup_selection = 0, transfer_selection = 0;
char dfile[FILSIZ+1] = "", ufile[FILSIZ+1] = "";
/* Saved video screens, attributes & cursor position */
char sav_buffer[(25*80)*2], sav_attr;
int sav_xy;
char video_save_area[SCR_BUF];
/*
* Main terminal program menu
*/
tty_main()
{
int i;
i = 0; /* Default to top of menu */
save_video(video_save_area);
redraw:
draw_title();
vdraw_box(0, SETROW, 79, 2);
show_settings();
for(;;) {
message("Select function and press ENTER");
if(vmenu(MAICOL, MENROW, main_menu, 0, &i))
continue;
switch(i) {
case 0 : /* Terminal Emulation */
if(!open_comm(flow))
break;
vcursor_line();
restore_screen();
ansi_term();
save_screen();
vcursor_off();
goto redraw;
case 1 : /* Download a file */
if(open_comm(0))
download(dfile);
break;
case 2 : /* Upload a file */
if(open_comm(0))
upload(dfile);
break;
case 3 : /* Setup serial port */
setup();
break;
case 4 : /* Exit to DOS */
Cclose();
restore_video(video_save_area);
return; } }
}
/*
* Open a file for read or write (with overwrite prompt)
*/
HANDLE openf(fname, rw)
char *fname, rw;
{
char c, omsg[80], *mode;
HANDLE fh;
mode = "read";
fh = open(fname, F_READ); /* First try and read the file */
if(rw) { /* If writing the file */
mode = "write";
if(fh) {
close(fh);
sprintf(omsg, "Overwrite existing %s (Y/N) ?", fname);
message(omsg);
do {
c = toupper(vgetc());
if((c == 0x1B) || (c == 'N'))
return 0; }
while(c != 'Y'); }
fh = open(fname, F_WRITE); }
if(!fh) {
sprintf(omsg,"Cannot %s %s (Press ENTER)", mode, fname);
message(omsg);
while(vgetc() != '\n'); }
return fh;
}
/*
* Open comm port with correct settings
*/
open_comm(flow)
char flow;
{
int mode;
/* Calculate the communications parameter value */
mode = ((par << 4) & 0x30) | /* parity type */
(data & 0x03) | /* # data bits */
((stop << 2) & 0x04) | /* # stop bits */
((par < 4) << 3); /* parity enable */
/* Open the communications port */
if(Copen(comm+1, baudvalue[baud], mode, SET_DTR|SET_RTS|OUTPUT_2)) {
message("Cannot open COM port (Press ENTER)");
while(vgetc() != '\n');
return 0; }
/* Remove transparency if XON/XOFF flow control */
disable();
Cflags = (flow) ? Cflags & ~TRANSPARENT : Cflags | TRANSPARENT;
enable();
return -1;
}
/*
* Draw the title header
*/
draw_title()
{
vopen();
V_ATTR = REVERSE;
vdraw_box(0, 0, 79, 2);
vgotoxy(1, 1);
vputf("", 26);
vputf("MICRO-Terminal Version 1.3", 52);
V_ATTR = NORMAL;
vcursor_off();
}
/*
* Draw the file transfer information box
*/
info_box(mode, filename)
char *mode, *filename;
{
vdraw_box(SUBCOL, MENROW+1, 50, 8);
vgotoxy(SUBCOL+2, MENROW+3);
vprintf("%-19s: %s", mode, filename);
vgotoxy(SUBCOL+2, MENROW+5);
vputs("Blocks transferred : 0");
vgotoxy(SUBCOL+2, MENROW+7);
vputs("Transfer status : ");
message("File transfer in progress (ESCAPE to abort)");
}
/*
* Update the transfer status field
*/
transfer_status(text)
char *text
{
vgotoxy(SUBCOL+23, MENROW+7);
vputf(text,10);
}
/*
* Show the current COM port settings
*/
show_settings()
{
vgotoxy(18, SETROW+1);
vprintf("COM%u: %5s,%2d,%5s,%2d Xon/Xoff %-8s",
comm+1, baudtext[baud], data+5, parity[par], stop+1, flowctrl[flow]);
}
/*
* Display a message
*/
message(ptr)
char *ptr;
{
vgotoxy(0, MSGROW);
vcleos();
vmessage(38 - strlen(ptr)/2, MSGROW, ptr);
}
/*
* Save the MICRO-TERMINAL video screen.
*/
save_screen()
{
sav_xy = V_XY;
sav_attr = V_ATTR;
copy_seg(get_ds(), sav_buffer, V_BASE, 0, (25*80)*2);
}
/*
* Restore the MICRO-TERMINAL video screen
*/
restore_screen()
{
copy_seg(V_BASE, 0, get_ds(), sav_buffer, (25*80)*2);
V_ATTR = sav_attr;
V_XY = sav_xy;
vupdatexy();
}
/*
* Comm port setup menu handler
*/
setup()
{
message("Select setting (ESCAPE to cancel)");
for(;;) {
show_settings();
if(vmenu(SUBCOL, MENROW+1, setup_menu, 0, &setup_selection))
return;
switch(setup_selection) {
case 0 : /* Comm port */
vmenu(SUBCOL+11,MENROW+2,onefour,-1,&comm);
break;
case 1 : /* baudrate */
vmenu(SUBCOL+11,MENROW+2,baudtext,-1,&baud);
break;
case 2 : /* Data bits */
vmenu(SUBCOL+11,MENROW+2,databits,-1,&data);
break;
case 3 : /* Parity */
vmenu(SUBCOL+11,MENROW+2,parity,-1,&par);
break;
case 4 : /* Stop bits */
vmenu(SUBCOL+11,MENROW+2,onetwo,-1,&stop);
break;
case 5 : /* Flow control */
vmenu(SUBCOL+11,MENROW+2,flowctrl,-1,&flow); } }
}
/*
* Terminal mode using ANSI (VT100) emulation
*/
ansi_term()
{
char c, xy_flag, *ptr;
unsigned x, y, state, value, parm, parms[5];
/* ANSI (VT100) Function key translation table */
static char *ansi_keys[] = {
"\x1B[A", "\x1B[B", "\x1B[D",